package com.ruoyi.system.ms.dataAuth.core;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler;
import com.ruoyi.system.ms.dataAuth.annations.MsDataAuth;
import com.ruoyi.system.ms.dataAuth.dto.DataAuthAnalysisMapperDto;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 数据权限拦截器
 *
 * @Author: 马帅
 **/
@Slf4j
public class DataAuthPermission implements MultiDataPermissionHandler {


    public static Map<String, DataAuthAnalysisMapperDto> authSqlCacheMap = new ConcurrentHashMap<>();
    public DataAuthPermission(){
        //模拟加入数据权限
        authSqlCacheMap.put("com.ruoyi.test.mapper.PcjItemMapper.selectPage",new DataAuthAnalysisMapperDto());
        authSqlCacheMap.put("com.ruoyi.test.mapper.PcjItemMapper.listPage",new DataAuthAnalysisMapperDto());
    }

    @SneakyThrows
    @Override
    public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {
        try {
            //只处理需要数据权限的数据
            DataAuthAnalysisMapperDto dto = authSqlCacheMap.get(mappedStatementId);
            if(dto!=null){
                Alias alias = table.getAlias();
                log.info("{} {} AS {} : NOT FOUND", mappedStatementId, table.getName(), table.getAlias());
                int lastIndex = mappedStatementId.lastIndexOf(".");
                String clzName  = mappedStatementId.substring(0, lastIndex);
                String methodName = mappedStatementId.substring(lastIndex + 1);
                Class<?> mapperClazz = Class.forName(clzName);
                //Method declaredMethod = mapperClazz.getDeclaredMethod(methodName);
                // 获取自身类中的所有方法，不包括继承。与访问权限无关
                return buildDataScopeByAnnotation(mappedStatementId);
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * DataScope注解方式，拼装数据权限
     *
     * @param mappedStatementId 执行的方法
     * @return
     */
    private Expression buildDataScopeByAnnotation(String mappedStatementId) {

        //=
        EqualsTo oneselfEqualsTo = new EqualsTo();
        oneselfEqualsTo.setLeftExpression(new Column("type"));
        oneselfEqualsTo.setRightExpression(new StringValue("1"));
        //in
        InExpression inExpression = new InExpression();
        inExpression.setLeftExpression(new Column("create_id"));
        List<Expression> expressions = new ArrayList<>();
        expressions.add(new StringValue("a1"));
        expressions.add(new StringValue("a2"));
        expressions.add(new StringValue("a3"));
        inExpression.setRightItemsList(new ExpressionList(expressions));
        // 构建 (type = '1' OR create_id IN ('a1', 'a2', 'a3'))
        OrExpression condition1 = new OrExpression(oneselfEqualsTo, inExpression);
        //like
        LikeExpression likeExpression = new LikeExpression();
        likeExpression.setLeftExpression(new Column("name"));
        likeExpression.setRightExpression(new StringValue("%电视%"));
        //!=
        NotEqualsTo notEqualsTo = new NotEqualsTo();
        notEqualsTo.setLeftExpression(new Column("update_id"));
        notEqualsTo.setRightExpression(new StringValue("1"));
        //构建 (name LIKE '%电视%' OR update_id != '1')
        OrExpression condition2 = new OrExpression(likeExpression, notEqualsTo);

        // 构建整体条件 (condition1 AND condition2)
        AndExpression finalCondition = new AndExpression(condition1, condition2);

        return finalCondition;
    }



}
